const redisClient = require('../db/redis')
const { db, execTransAction } = require('../db/mysql')
const bcryptjs = require('bcryptjs')
const path = require('path')
const jsonWebToken = require('jsonwebtoken')
const config = require('../config/index')
const fs = require('fs')
const { number } = require('joi')
const axios = require('axios')
const createOrderNumber = require('../utils/createOrderNo')
const alipaySdk = require('../utils/aliPay')
const AlipayFormData = require('alipay-sdk/lib/form').default

//#region
// 用户注册账号
exports.userRegister = async (req, res) => {
  // 1. 验证用户输入的验证码是否正确
  const code = req.body.code
  const redisCode = await redisClient.get('sms_' + req.body.phone)

  // 验证码不存在
  if (!redisCode) {
    return res.cc('验证码已过期或者手机号错误！')
  }

  // 验证码错误
  if (code !== redisCode) {
    return res.cc('验证码错误！')
  }

  // 2. 验证手机号是否注册
  const sql = `select * from users where phone=?`
  db.query(sql, req.body.phone, (err, result) => {
    if (err) {
      return res.cc(err)
    }
    if (result.length !== 0) {
      return res.cc('该手机号已注册，请更换手机号重试！')
    }

    // 3. 验证用户名是否被占用
    const sql = `select * from users where name=?`
    db.query(sql, req.body.account, async (err, result) => {
      if (err) {
        return res.cc(err)
      }
      if (result.length !== 0) {
        return res.cc('用户名被占用，请更换用户名重试！')
      }

      // 4. 注册账号
      const sql = `insert into users set ?`
      const date = new Date()

      // 将密码进行加密
      const password = bcryptjs.hashSync(req.body.password)
      // 获取用户默认头像
      const avatar = path.join('/api/user_avatar/lMkqNXyJvj.png')
      // 执行sql语句注册用户
      db.query(sql, { name: req.body.account, password, phone: req.body.phone, nickname: req.body.nickname, create_time: date, update_time: date, avatar }, async (err, result) => {
        // 执行sql语句失败
        if (err) {
          return res.cc(err)
        }

        // 注册失败
        if (result.affectedRows !== 1) {
          return res.cc('注册失败！')
        }

        // 删除redis数据库中的验证码
        await redisClient.del('sms_' + req.body.phone)

        //注册成功
        res.cc('注册成功', 0)
      })
    })
  })
}

// 用户登录
exports.userLogin = async (req, res) => {
  if (req.body.phone) {
    // 第一种登录方式,使用手机验证码登录
    // 1. 检查手机号是否已经注册
    const sql = `select * from users where phone=?`
    db.query(sql, req.body.phone, async (err, result) => {
      if (err) {
        return res.cc(err)
      }
      if (result.length === 0) {
        return res.cc('该手机号还未注册！')
      }

      // 2. 检查验证码是否过期
      const redisCode = await redisClient.get('sms_' + req.body.phone)
      if (!redisCode) {
        return res.cc('验证码已过期或手机号错误！')
      }

      // 3. 检查验证码是否错误
      if (redisCode !== req.body.code) {
        return res.cc('验证码错误！')
      }

      // 4. 生成用户token返回给用户并将其保存在redis数据库中
      const token = jsonWebToken.sign({ ...result[0], password: '', email: '' }, config.secretKey, { expiresIn: '48h' })
      // 将用户token保存在redis数据库中
      await redisClient.set('user_token_' + result[0].id, 'Bearer ' + token)
      await redisClient.expire('user_token_' + result[0].id, 172800)
      // 删除redis数据库中的验证码
      await redisClient.del('sms_' + req.body.phone)
      // 断开redis数据库连接

      // 将token返回给用户
      res.send({
        code: 0,
        msg: '登录成功',
        token: 'Bearer ' + token
      })
    })
  } else {
    // 第二种登录方式，使用账号密码登录
    // 1. 检查账号是否存在
    const sql = `select * from users where name=?`
    db.query(sql, req.body.account, async (err, result) => {
      if (err) {
        return res.cc(err)
      }

      if (result.length === 0) {
        return res.cc('该账号不存在！')
      }

      // 2. 检查登录密码是否正确
      const isTrue = bcryptjs.compareSync(req.body.password, result[0].password)
      if (!isTrue) {
        return res.cc('密码错误！')
      }

      // 3. 生成用户token返回给用户并将其保存在redis数据库中
      const token = jsonWebToken.sign({ ...result[0], password: '', email: '' }, config.secretKey, { expiresIn: '48h' })
      // 将用户token保存在redis数据库中
      await redisClient.set('user_token_' + result[0].id, 'Bearer ' + token)
      await redisClient.expire('user_token_' + result[0].id, 172800)
      // 断开redis数据库连接
      // 将token返回给用户
      res.send({
        code: 0,
        msg: '登录成功',
        token: 'Bearer ' + token
      })
    })
  }
}

// 用户忘记密码
exports.userForget = (req, res) => {
  // 1. 验证用户提供的账号是否已经注册
  const sql = `select * from users where phone=?`
  db.query(sql, req.body.phone, async (err, result) => {
    if (err) return res.cc(err)
    if (result.length === 0) return res.cc('该手机号未注册！')

    // 2. 验证码是否正确
    const redisCode = await redisClient.get('sms_' + req.body.phone)
    if (!redisCode) {
      return res.cc('验证码已过期或手机号错误！')
    }

    if (redisCode !== req.body.code) {
      return res.cc('验证码错误！')
    }
    // 3. 将密码进行加密之后保存到数据库
    const password = bcryptjs.hashSync(req.body.newPassword)
    const sql = `update users set password=? where phone=?`
    db.query(sql, [password, req.body.phone], async (err, result) => {
      // 执行sql出错
      if (err) {
        return res.cc(err)
      }

      if (result.affectedRows !== 1) {
        return res.cc('重置密码失败！')
      }

      // 4. 删除redis中的验证码
      await redisClient.del('sms_' + req.body.phone)

      res.cc('重置密码成功！', 0)
    })
  })
}

// 用户退出登录
exports.userLogout = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 2. 删除redis数据库中得token
  const result = await redisClient.del('user_token_' + req.auth.id)

  // 3. 退出登录成功，返回响应
  if (result === 1) {
    res.cc('退出登录成功！', 0)
  } else {
    res.cc('退出登录失败！')
  }
}

// 用户注销账号
exports.userCancellation = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  const sqlArr = [
    // 删除用户账号
    {
      sql: `delete from users where id=?`,
      values: req.auth.id
    },
    // 删除用户收藏的商品
    {
      sql: `delete from users where id=?`,
      values: req.auth.id
    },
    // 删除用户订单
    {
      sql: `delete from user_orders where user_id=?`,
      values: req.auth.id
    },
    // 删除用户购物车
    {
      sql: `delete from user_shopcarts where user_id=?`,
      values: req.auth.id
    },
    // 删除用户收货地址
    {
      sql: `delete from user_address where user_id=?`,
      values: req.auth.id
    }
  ]
  try {
    // 删除用户信息
    await execTransAction(sqlArr)
    // 删除用户token
    await redisClient.del('user_token_' + req.auth.id)
    res.cc('注销账号成功！', 0)
  } catch (err) {
    console.log(err)
    res.cc(err)
  }
}

// 获取用户信息
exports.getUserInfo = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 2. 根据用户id查询mysql数据库中得账号信息
  const getUserInfoSql = `select * from users where id=?`
  db.query(getUserInfoSql, req.auth.id, (err, result) => {
    if (err) return res.cc(err)
    // 3. 将查询到得结果返回给用户
    if (result.length !== 1) {
      res.cc('获取用户信息失败！')
    } else {
      res.send({
        code: 0,
        msg: '获取用户信息成功！',
        data: {
          ...result[0],
          password: '',
          birthday: new Date(result[0].birthday).toLocaleDateString(),
          avatar: result[0].avatar.replace(/\\/g, '/')
        }
      })
    }
  })
}

// 上传用户头像
exports.updateAvatar = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 读取用户原来的头像
  const sql = `select avatar from users where id=?`
  db.query(sql, req.auth.id, (err, result) => {
    if (err) return res.cc(err)
    if (result.length === 0) return res.cc('获取用户头像失败')
    const filePath = result[0].avatar.replace('/api', './public')
    // 2. 将用户传递过来得base64路径保存到本地
    const imgData = req.body.avatar
    const base64Data = imgData.replace(/^data:image\/\w+;base64,/, '')

    const Readable = require('stream').Readable

    const imgBuffer = Buffer.from(base64Data, 'base64')

    const s = new Readable()

    s.push(imgBuffer)
    s.push(null)
    const time = new Date().getTime()
    try {
      s.pipe(fs.createWriteStream('./public/user_avatar/' + time + req.auth.id + req.body.type))
      // 3. 将本地得路径保存在在mysql数据库
      const path = '/api/user_avatar/' + time + req.auth.id + req.body.type
      const sql = `update users set avatar=? where id=?`

      db.query(sql, [path, req.auth.id], (err, result) => {
        if (err) return res.cc(err)
        if (result.affectedRows !== 1) return res.cc('更新用户头像失败！')
        const pathArr = filePath.split('/')
        if (pathArr[-1] !== 'lMkqNXyJvj.png') {
          // 删除原来的头像
          fs.unlink(filePath, (err) => {
            if (err) throw err
          })
        }

        // 4.返回用户响应
        res.send({
          code: 0,
          msg: '更新用户头像成功！',
          data: {
            avatar: path
          }
        })
      })
    } catch (err) {
      res.cc(err)
    }
  })
}

// 用户修改密码
exports.updatePassword = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 1. 旧密码时候与数据库中密码相同
  const sql = `select * from users where id=?`
  db.query(sql, req.auth.id, (err, result) => {
    if (err) {
      return res.cc(err)
    }
    if (result.length === 0) {
      return res.cc('用户信息不存在')
    }
    const oldPwdIsTrue = bcryptjs.compareSync(req.body.password, result[0].password)

    if (!oldPwdIsTrue) {
      return res.cc('旧密码错误！')
    }
    // 2. 将新密码进行加密后保存到数据库
    const password = bcryptjs.hashSync(req.body.newPassword)
    const sql = `update users set password=? where id=?`
    db.query(sql, [password, req.auth.id], async (err, result) => {
      if (err) {
        return res.cc(err)
      }
      if (result.affectedRows !== 1) {
        return res.cc('更新密码失败！')
      }
      // 6. 删除redis验证码和用户token
      await redisClient.del('sms_' + req.body.phone)
      await redisClient.del('user_token_' + req.auth.id)
      // 关闭redis数据库

      // 7. 返回响应
      res.cc('更新密码成功', 0)
    })
  })
}

// 用户完善个人信息
exports.updateUserinfo = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 1. 根据用户id查询数据库信息判断用户传递手机号与数据库手机号是否一致
  if (req.body.phone !== req.auth.phone) return res.cc('手机号不允许更换！')
  const sql = `select * from users where id=?`
  db.query(sql, req.auth.id, (err, result) => {
    if (err) return res.cc(err)
    if (result.length !== 1) return res.cc('用户信息不存在！')
    if (req.body.phone !== result[0].phone) return res.cc('手机号不允许更换！')
    // 2. 更新数据库信息
    const sql = `update users set name=?, nickname=?, email=?, sex=?, birthday=?, update_time=? where id=?`
    db.query(sql, [req.body.account, req.body.nickname, req.body.email, req.body.sex, req.body.birthday, new Date().toLocaleDateString(), req.auth.id], (err, result) => {
      if (err) return res.cc(err)
      if (result.affectedRows !== 1) return res.cc('更新用户信息失败！')
      // 3. 返回响应
      res.cc('更新用户信息成功！', 0)
    })
  })
}

// 用户新增收货地址
exports.addAddress = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 1. 判断该收货地址是否是默认地址
  if (req.body.status === 1) {
    // 2. 如果是默认地址就先将数据库中得收货地址全部设置未非默认地址
    const sql = `update user_address set status=0 where user_id=?`
    db.query(sql, req.auth.id, (err, result) => {
      if (err) return res.cc(err)
    })
  }

  // 3. 判断当前新增的地址是否存在
  const sql = `select * from user_address where user_id=? and name=? and phone=? and province=? and city=? and country=? and address=? and areacode=?`
  db.query(sql, [req.auth.id, req.body.name, req.body.phone, req.body.province, req.body.city, req.body.country, req.body.address, req.body.areacode], (err, result) => {
    if (err) return res.cc(err)
    if (result.length !== 0) return res.cc('该收货地址已存在！')
    // 4. 将用户提供得地址进行保存到数据库中
    const sql = `insert into user_address set ?`
    db.query(sql, { name: req.body.name, phone: req.body.phone, province: req.body.province, city: req.body.city, country: req.body.country, address: req.body.address, user_id: req.auth.id, status: req.body.status, areacode: req.body.areacode }, (err, result) => {
      if (err) return res.cc(err)
      if (result.affectedRows !== 1) return res.cc('新增收货地址失败！')
      // 4. 返回响应
      res.cc('新增收货地址成功！', 0)
    })
  })
}

// 编辑用户收货地址
exports.updateAddress = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 获取用户传递的地址id
  let path = req.path.split('/')
  path = path[path.length - 1]
  if (!/^\d{1,}$/.test(path)) return res.cc('收货地址id必须为数字！')
  // 1. 根据id查询数据库中得数据
  const sql = `select * from user_address where id=?`
  db.query(sql, path, (err, result) => {
    if (err) return res.cc(err)
    if (result.length === 0) return res.cc('收货地址id对应收货地址信息不存在！')

    // 2. 判断需要修改的地址在数据库是否已经存在
    const sql = `select * from user_address where name=? and phone=? and province=? and city=? and country=? and address=? and areacode=? and id!=? and user_id=?`
    db.query(sql, [req.body.name, req.body.phone, req.body.province, req.body.city, req.body.country, req.body.address, req.body.areacode, path, req.auth.id], (err, result) => {
      if (err) return res.c(err)
      if (result.length !== 0) return res.cc('当前地址已经存在！')

      // 3. 判断当前地址是否设置为默认地址,如果设置为
      if (req.body.status === 1) {
        const sql = `update user_address set status=0 where user_id=?`
        db.query(sql, [req.auth.id], (err, result) => {
          if (err) return res.cc(err)
        })
      }
      // 4. 将用户发送得数据进行修改
      const sql = `update user_address set ? where id=? and user_id=?`
      db.query(sql, [{ name: req.body.name, phone: req.body.phone, province: req.body.province, city: req.body.city, country: req.body.country, address: req.body.address, status: req.body.status, areacode: req.body.areacode }, path, req.auth.id], (err, result) => {
        if (err) return res.cc(err)
        if (result.affectedRows !== 1) return res.cc('修改收货地址失败！')
        // 3. 返回修改结果
        res.cc('修改收货地址成功！', 0)
      })
    })
  })
}

// 删除用户收货地址
exports.deleteAddress = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 获取用户传递的地址id
  let path = req.path.split('/')
  path = path[path.length - 1]
  if (!/^\d{1,}$/.test(path)) return res.cc('收货地址id必须为数字！')

  // 1. 删除数据库中用户地址
  const sql = `delete from user_address where id=? and user_id=?`
  db.query(sql, [path, req.auth.id], (err, result) => {
    if (err) return res.cc(err)
    if (result.affectedRows !== 1) return res.cc('删除收货地址失败！')
    // 2. 删除成功返回响应
    res.cc('删除收货地址成功！', 0)
  })
}

// 获取用户收货地址列表
exports.getAddressList = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 1. 根据用户id查询数据库中收货地址
  const sql = `select * from user_address where user_id=?`
  db.query(sql, req.auth.id, (err, result) => {
    if (err) return res.cc(err)
    // 2. 将查询到的结果返回给用户
    res.send({
      code: 0,
      msg: '获取收货地址列表成功！',
      data: result
    })
  })
}

// 根据id获取用户收货地址
exports.getAddressById = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 获取用户传递的地址id
  let path = req.path.split('/')
  path = path[path.length - 1]
  if (!/^\d{1,}$/.test(path)) return res.cc('收货地址id必须为数字！')

  // 1. 根据用户id和地址id查询收货地址
  const sql = `select * from user_address where id=? and user_id=?`
  db.query(sql, [path, req.auth.id], (err, result) => {
    if (err) return res.cc(err)
    if (result.length === 0) return res.cc('获取地址信息失败！')
    // 2. 将查询结果返回给用户
    res.send({
      code: 0,
      msg: '获取地址信息成功！',
      data: { ...result[0] }
    })
  })
}

// 获取轮播图展示商品
exports.getBannerGoods = async (req, res) => {
  // 1. 定义sql语句获取数据库商品信息
  const sql = `select * from goods where is_banner='1'`
  db.query(sql, (err, result) => {
    if (err) return res.cc(err)
    // 当所有数据低于四条直接返回所有数据
    if (result.length < 4) {
      // 3.返回响应
      res.send({
        code: 0,
        msg: '获取轮播图数据成功！',
        data: result
      })
    } else {
      const maxNUm = result.length
      // 2. 随机返回四个商品数据
      const numberArr = []
      for (let i = 0; i < 4; i++) {
        const randomNumber = Math.floor(Math.random() * (maxNUm - 0))
        if (numberArr.indexOf(randomNumber) === -1) {
          numberArr.push(randomNumber)
        } else {
          i--
        }
      }
      numberArr.sort()
      const results = []
      numberArr.forEach((index) => {
        // 本身数组中就保存的是下标
        results.push(result[index])
      })
      // 3.返回响应
      res.send({
        code: 0,
        msg: '获取轮播图数据成功！',
        data: results
      })
    }
  })
}

// 获取热卖商品
exports.getHotGoods = (req, res) => {
  // 1. 定义sql语句查询数据库中热门商品
  const sql = `select * from goods order by goods_sell_num desc limit 8`
  // 2. 返回8条响应
  db.query(sql, (err, result) => {
    if (err) return res.cc(err)
    // 3. 返回响应
    res.send({
      code: 0,
      msg: '热卖商品数据成功！',
      data: result
    })
  })
}

// 获取最新商品数据
exports.getNewGoodsList = (req, res) => {
  const page = req.query.page
  // 1. 定义sql数据获取数据库数据
  let sql = `select * from goods where is_new=1 limit ${(page - 1) * 10}, ${10}`
  // 2. 如果用户没有传递page就返回8条数据
  if (!page) {
    sql = `select * from goods where is_new=1 limit 8`
    db.query(sql, (err, result) => {
      if (err) return res.cc(err)
      res.send({
        code: 0,
        msg: '获取最新商品成功！',
        data: result
      })
    })
  } else {
    // 3. 如果用户传递了page参数每次返回10条数据
    db.query(sql, (err, result) => {
      if (err) return res.cc(err)
      // 4. 对数据进行响应的处理并返回处理结果
      res.send({
        code: 0,
        msg: '获取最新商品成功！',
        data: result
      })
    })
  }
}

// 获取店铺推荐商品
exports.getRecommendGoods = (req, res) => {
  // 1. 获取用户传递的page
  const page = req.query.page
  // 2. 如果用户没有传递page返回8条数据
  if (!page) {
    const sql = `select * from goods where is_recommend=1 limit 8`
    db.query(sql, (err, result) => {
      if (err) return res.cc(err)
      res.send({
        code: 0,
        msg: '获取推荐商品成功！',
        data: result
      })
    })
  } else {
    // 3. 定义sql语句查询数据库中的数据
    const sql = `select * from goods where is_recommend=1 limit ${(page - 1) * 10}, ${10}`
    db.query(sql, (err, result) => {
      if (err) return res.cc(err)
      // 6. 返回数据
      res.send({
        code: 0,
        msg: '获取推荐商品数据成功！',
        data: result
      })
    })
  }
}

// 获取其他商品
exports.getAntherGoodsList = (req, res) => {
  // 1. 获取用户传递的page参数和limit参数
  const page = req.query.page
  const limit = req.query.limit
  // 2. 定义sql语句查询数据库商品数据
  const sql = `select * from goods where is_new=0 and is_recommend=0 limit ${(page - 1) * limit}, ${limit}`
  db.query(sql, (err, result) => {
    if (err) return res.cc(err)
    // 3. 返回响应
    res.send({
      code: 0,
      msg: '获取其他商品数据成功！',
      data: result
    })
  })
}

// 根据商品id获取商品信息
exports.getGoodsInfoById = (req, res) => {
  // 1. 获取请求路径中的id参数
  const pathArr = req.path.split('/')
  const id = pathArr[pathArr.length - 1]
  if (typeof id === number) return res.cc('商品id必须是一个数字')
  // 2. 根据id获取数据库中商品数据信息
  const sql = `select * from goods where id=?`
  db.query(sql, id, (err, result) => {
    if (err) return res.cc(err)
    // 3. 返回响应数据
    if (result.length === 0) return res.cc('获取商品详情数据失败！')
    res.send({
      code: 0,
      msg: '商品详情数据获取成功！',
      data: result[0]
    })
  })
}
// 用户收藏商品
exports.AddLike = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 添加到收藏
  const sql = `insert into user_collection set ?`
  db.query(sql, { goods_id: req.body.id, user_id: req.auth.id }, (err, result) => {
    if (err) return res.cc(err)
    // 3. 返回响应
    if (result.affectedRows !== 1) return res.cc('收藏失败!')
    res.cc('已收藏!', 0)
  })
}

// 用户取消收藏
exports.CancelLike = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 删除用户收藏数据
  const sql = `delete from user_collection where id=? and user_id=?`
  db.query(sql, [req.body.id, req.auth.id], (err, result) => {
    // 3. 返回响应
    if (err) return res.cc(err)
    if (result.affectedRows !== 1) return res.cc('取消收藏失败!')
    res.cc('已取消收藏!', 0)
  })
}

// 根据商品id获取收藏信息
exports.getCollection = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 定义sql语句获取收藏信息
  const sql = `select * from user_collection where goods_id=? and user_id=?`
  db.query(sql, [req.query.id, req.auth.id], (err, result) => {
    if (err) return res.cc(err)
    // 3. 返回响应
    if (result.length === 0) return res.cc('该商品未收藏!', 0)
    res.send({
      code: 0,
      msg: '获取商品收藏信息成功!',
      data: result[0]
    })
  })
}

// 获取所有收藏商品列表信息
exports.getAllCollectionGoods = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 获取前端传递的数据
  const page = req.query.page
  const limit = req.query.limit
  // 2. 获取所有的收藏数据
  const sql = `select * from user_collection where user_id=?`
  db.query(sql, req.auth.id, (err, result) => {
    if (err) return res.cc(err)
    if (result.length === 0) {
      return res.send({
        code: 0,
        msg: '收藏信息获取成功!',
        data: result
      })
    } else if (result.length > (page - 1) * limit && result.length < page * limit) {
      let count = 0
      const results = {
        code: 0,
        msg: '收藏信息获取成功!',
        data: []
      }
      const sql = `select * from goods where id=?`
      for (let i = (page - 1) * limit; i < result.length; i++) {
        db.query(sql, result[i].goods_id, (err, resultGoods) => {
          if (err) throw err
          if (resultGoods.length === 0) {
            // 没有该收藏商品信息,自动删除该收藏信息
            const sql = `delete from user_collection where id=? and user_id=?`
            db.query(sql, [result[i].id, req.auth.id], (err, result) => {
              if (err) throw err
              if (result.affectedRows === 1) {
                i--
              }
            })
          } else {
            count++
            // 将商品信息添加到响应结果中
            results.data.push({ collection_id: result[i].id, ...resultGoods[0] })
            if (count === result.length - (page - 1) * limit) {
              return res.send(results)
            }
          }
        })
      }
    } else if (result.length >= page * limit) {
      const results = {
        code: 0,
        msg: '收藏信息获取成功!',
        data: []
      }
      const sql = `select * from goods where id=?`
      let count = 0
      for (let i = (page - 1) * limit; i < limit * page; i++) {
        db.query(sql, result[i].goods_id, (err, resultGoods) => {
          if (err) throw err
          if (resultGoods.length === 0) {
            // 没有该收藏商品信息,自动删除该收藏信息
            const sql = `delete from user_collection where id=? and user_id=?`
            db.query(sql, [result[i].id, req.auth.id], (err, result) => {
              if (err) throw err
              if (result.affectedRows === 1) {
                i--
              }
            })
          } else {
            // 将商品信息添加到响应结果中
            count++
            results.data.push({ collection_id: result[i].id, ...resultGoods[0] })
            if (count === limit) {
              return res.send(results)
            }
          }
        })
      }
    } else {
      res.send({
        code: 0,
        msg: '收藏信息获取成功!',
        data: []
      })
    }
  })
}

// 添加到购物车
exports.addCartHandle = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取用户提交的商品id以及添加到购物车的数量并判断库存是否充足
  const count = req.body.count
  const id = req.body.id
  const sql = `select * from goods where id=?`
  db.query(sql, id, (err, result) => {
    if (err) return res.cc(err)
    if (result.length === 0) return res.cc('商品信息不存在！')
    // 判断商品库存是否充足
    if (result[0].goods_stock < count) return res.cc('商品库存不足！')
    // 3 查询购物车中是否存在该条数据
    const sql = `select * from user_shopcarts where goods_id=? and user_id=?`
    db.query(sql, [id, req.auth.id], (err, result) => {
      if (err) return res.cc(err)
      if (result.length === 0) {
        // 4. 将商品添加到购物车
        const sql = `insert into user_shopcarts set ?`
        db.query(sql, { user_id: req.auth.id, goods_id: id, goods_num: count }, (err, result) => {
          if (err) return res.cc(err)
          if (result.affectedRows !== 1) return res.cc('添加购物车失败！')
          res.cc('添加购物车成功！', 0)
        })
      } else {
        // 5. 修改购物车商品数量
        const sql = `update user_shopcarts set goods_num=? where goods_id=? and user_id=?`
        db.query(sql, [result[0].goods_num + count, id, req.auth.id], (err, result) => {
          if (err) return res.cc(err)
          if (result.affectedRows === 0) return res.cc('添加购物车失败!')
          res.cc('添加购物车成功！', 0)
        })
      }
    })
  })
}

// 获取购物车数量
exports.getShopCartCount = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取购物车数量
  const sql = `select * from user_shopcarts where user_id=?`
  db.query(sql, req.auth.id, (err, result) => {
    if (err) return res.cc(err)
    res.send({
      code: 0,
      msg: '获取购物车数量成功！',
      data: { count: result.length }
    })
  })
}

// 获取所有购物车商品
exports.getAllShopCartGoods = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取购物车数量
  const sql = `select * from user_shopcarts where user_id=?`
  db.query(sql, req.auth.id, (err, result) => {
    if (err) return res.cc(err)
    if (result.length === 0) {
      res.send({
        code: 0,
        msg: '获取购物车数量成功！',
        data: result
      })
    } else {
      let count = 0
      const data = []
      const sql = `select * from goods where id=?`
      // 3. 遍历结果获取购物车id所对应的商品信息
      for (let i = 0; i < result.length; i++) {
        db.query(sql, result[i].goods_id, (err, results) => {
          if (err) return res.cc(err)
          if (results.length === 0) {
            // 当前id商品信息不存在, 删除当前id在购物车中的数据
            count++
            const sql = `delete from user_shopcarts where id=? and user_id=?`
            db.query(sql, [result[i].id, req.auth.id], (err, results) => {
              if (err) {
              }
              // 4. 返回响应
              if (count === result.length) {
                res.send({
                  code: 0,
                  msg: '购物车数据获取成功！',
                  data
                })
              }
            })
          } else {
            count++
            data.push({
              id: result[i].id,
              goods_data: results[0],
              count: result[i].goods_num
            })
            // 4. 返回响应
            if (count === result.length) {
              res.send({
                code: 0,
                msg: '购物车数据获取成功！',
                data
              })
            }
          }
        })
      }
    }
  })
}

// 根据id删除购物车数据
exports.deleteShopCartData = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }
  // 2. 获取用户传递的id数据
  let ids = req.body.ids
  if (!/\d/.test(ids[ids.length - 1])) {
    ids = ids.slice(0, ids.length - 1).split(',')
  } else {
    ids = ids.split(',')
  }

  // 3. 遍历ids挨个将数据库数据删除
  const sql = `delete from user_shopcarts where id=? and user_id=?`
  const success = []
  const fail = []
  for (let i = 0; i < ids.length; i++) {
    db.query(sql, [ids[i], req.auth.id], (err, result) => {
      if (err || result.affectedRows !== 1) {
        fail.push(ids[i])
      } else if (result.affectedRows === 1) {
        success.push(ids[i])
      }

      if (i === ids.length - 1) {
        res.send({
          code: 0,
          msg: '操作执行成功！',
          data: {
            success,
            fail
          }
        })
      }
    })
  }
}

// 修改购物车商品数量
exports.editShopCartCount = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取用户传递的商品id判断数据库库存是否充足
  const sql = `select goods_stock from goods where id=?`
  db.query(sql, req.body.goods_id, (err, result) => {
    if (err) return res.cc(err)
    if (result.length === 0) return res.cc('商品信息不存在！')
    if (result[0].goods_stock < req.body.count) return res.cc('商品库存数量不足！')

    // 3. 修改购物车中的商品数量
    const sql = `update user_shopcarts set goods_num=? where id=? and user_id=?`
    db.query(sql, [req.body.count, req.body.id, req.auth.id], (err, result) => {
      if (err) return res.cc(err)
      if (result.affectedRows !== 1) return res.cc('修改商品数量失败！')
      res.cc('修改商品数据成功！', 0)
    })
  })
}

// 获取所有商品
exports.getAllGoodsByCateId = (req, res) => {
  // 1. 获取用户传递的分类id
  const cate_id = req.query.id
  const page = req.query.page
  const limit = req.query.limit
  // 2. 根据id获取数据库中的数据
  const sql = `select * from goods where cate_id=?`
  db.query(sql, cate_id, (err, result) => {
    if (err) return res.cc(err)
    // 3. 根据传递过来的page参数处理数据
    if (result.length === 0) {
      return res.send({
        code: 0,
        msg: '该分类下暂无商品！',
        data: result
      })
    } else if (result.length > (page - 1) * limit && result.length < page * limit) {
      // 商品数量不足以前端请求数量
      const results = {
        code: 0,
        msg: '获取商品数据成功!',
        data: []
      }
      for (let i = (page - 1) * limit; i < result.length; i++) {
        results.data.push(result[i])
      }
      res.send(results)
    } else if (result.length >= page * limit) {
      // 数据充足
      const results = {
        code: 0,
        msg: '获取商品数据成功!',
        data: []
      }
      for (let i = (page - 1) * limit; i < limit * page; i++) {
        results.data.push(result[i])
      }
      res.send(results)
    }
  })
}

// 获取一级分类
exports.getCateOneLevel = (req, res) => {
  // 1. 获取数据库分类信息
  const sql = `select * from goods_cates where level='一级'`
  db.query(sql, (err, result) => {
    if (err) return res.cc(err)
    res.send({
      code: 0,
      msg: '获取一级分类数据成功！',
      data: result
    })
  })
}

// 获取二级分类
exports.getCateTwoLevel = (req, res) => {
  // 1. 获取一级分类id
  const cate_id = req.query.id
  if (!cate_id) return res.cc('缺少参数id！')
  // 2. 根据分类id获取数据库信息
  const sql = `select * from goods_cates where level='二级' and super_id=?`
  db.query(sql, cate_id, (err, result) => {
    if (err) return res.cc(err)
    res.send({
      code: 0,
      msg: '二级分类数据获取成功！',
      data: result
    })
  })
}

// 搜索商品数据
exports.searchHandler = (req, res) => {
  const keyword = req.query.keyword
  // 1. 使用模糊查询获取数据并获取该分类所属分类
  const sql = `SELECT * from goods where goods_name like ?`
  db.query(sql, `%${keyword}%`, async (err, data) => {
    console.log(err)
    if (err) return res.cc(err)
    // 2. 查询数据库中是否已经存在该关键词
    const sql = `select * from search_history where user_id=? and name=?`
    db.query(sql, [req.auth.id, keyword], (err, result) => {
      if (err)
        return res.send({
          code: 0,
          save: '保存搜索历史失败！',
          msg: '搜索成功！',
          data
        })

      if (result.length === 0) {
        // 3. 将搜索关键词保存在搜索历史中
        const sql = `insert into search_history set ?`
        db.query(sql, [{ name: keyword, user_id: req.auth.id }], (err, result) => {
          if (err)
            return res.send({
              code: 0,
              save: '保存搜索历史失败！',
              msg: '暂无相关商品数据！',
              data
            })
          if (result.affectedRows !== 1) {
            res.send({
              code: 0,
              save: '保存搜索历史失败！',
              msg: '搜索成功！',
              data
            })
          } else {
            // 4. 查询热门搜索中是否有该搜索关键字
            const sql = `select * from hot_history where name=?`
            db.query(sql, keyword, (err, result) => {
              if (err)
                return res.send({
                  code: 0,
                  saveHistory: '保存搜索历史成功！',
                  saveHotHistory: '保存热门搜索失败！',
                  msg: '搜索成功！',
                  data
                })

              if (result.length === 0) {
                // 数据库中没有该关键词，向数据库中插入1条数据
                const sql = `insert into hot_history set ?`
                db.query(sql, { name: keyword }, (err, result) => {
                  if (err)
                    return res.send({
                      code: 0,
                      saveHistory: '保存搜索历史成功！',
                      saveHotHistory: '保存热门搜索失败！',
                      msg: '搜索成功！',
                      data
                    })
                  // 插入失败
                  if (result.affectedRows !== 1) {
                    res.send({
                      code: 0,
                      saveHistory: '保存搜索历史成功！',
                      saveHotHistory: '保存热门搜索失败！',
                      msg: '搜索成功！',
                      data
                    })
                  } else {
                    // 插入成功
                    res.send({
                      code: 0,
                      saveHistory: '保存搜索历史成功！',
                      saveHotHistory: '保存热门搜索成功！',
                      msg: '搜索成功！',
                      data
                    })
                  }
                })
              } else {
                // 数据库中存在该关键词，让数据库中的数据增加1条
                const sql = `update hot_history set count=? where id=?`
                db.query(sql, [result[0].count + 1, result[0].id], (err, result) => {
                  if (err)
                    return res.send({
                      code: 0,
                      saveHistory: '保存搜索历史成功！',
                      saveHotHistory: '保存热门搜索失败！',
                      msg: '搜索成功！',
                      data
                    })
                  // 修改失败！
                  if (result.affectedRows !== 1) {
                    res.send({
                      code: 0,
                      saveHistory: '保存搜索历史成功！',
                      saveHotHistory: '保存热门搜索失败！',
                      msg: '搜索成功！',
                      data
                    })
                  } else {
                    res.send({
                      code: 0,
                      saveHistory: '保存搜索历史成功！',
                      saveHotHistory: '保存热门搜索成功！',
                      msg: '搜索成功！',
                      data
                    })
                  }
                })
              }
            })
          }
        })
      } else {
        // 5. 将搜索关键词保存到热门搜索中
        const sql = `select * from hot_history where name=?`
        db.query(sql, keyword, (err, result) => {
          if (err)
            return res.send({
              code: 0,
              saveHistory: '保存搜索历史成功！',
              saveHotHistory: '保存热门搜索失败！',
              msg: '搜索成功！',
              data
            })

          if (result.length === 0) {
            // 数据库中没有该关键词，向数据库中插入1条数据
            const sql = `insert into hot_history set ?`
            db.query(sql, { name: keyword }, (err, result) => {
              if (err)
                return res.send({
                  code: 0,
                  msg: '搜索成功！',
                  saveHotHistory: '保存热门搜索失败！',
                  data
                })
              // 插入失败
              if (result.affectedRows !== 1) {
                res.send({
                  code: 0,
                  msg: '搜索成功！',
                  saveHotHistory: '保存热门搜索失败！',
                  data
                })
              } else {
                // 插入成功
                res.send({
                  code: 0,
                  msg: '搜索成功！',
                  saveHotHistory: '保存热门搜索成功！',
                  data
                })
              }
            })
          } else {
            // 数据库中存在该关键词，让数据库中的数据增加1条
            const sql = `update hot_history set count=? where id=?`
            db.query(sql, [result[0].count + 1, result[0].id], (err, result) => {
              if (err)
                return res.send({
                  code: 0,
                  msg: '搜索成功！',
                  saveHotHistory: '保存热门搜索失败！',
                  data
                })
              // 修改失败！
              if (result.affectedRows !== 1) {
                res.send({
                  code: 0,
                  msg: '搜索成功！',
                  saveHotHistory: '保存热门搜索失败！',
                  data
                })
              } else {
                res.send({
                  code: 0,
                  msg: '搜索成功！',
                  saveHotHistory: '保存热门搜索成功！',
                  data
                })
              }
            })
          }
        })
      }
    })
  })
}

// 获取热门搜索
exports.getHotSearch = (req, res) => {
  // 1. 定义sql语句获取搜索历史数据
  const sql = `select * from hot_history order by count desc limit 15`
  db.query(sql, (err, result) => {
    if (err) return res.cc(err)
    // 返回结果
    res.send({
      code: 0,
      msg: '获取热门搜索成功！',
      data: result
    })
  })
}

// 获取搜索历史
exports.getHistorySearch = async (req, res) => {
  // 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 1. 定义sql语句查询数据
  const sql = `select * from search_history where user_id=?`
  db.query(sql, req.auth.id, (err, result) => {
    if (err) return res.cc(err)
    res.send({
      code: 0,
      msg: '获取搜索历史数据成功！',
      data: result
    })
  })
}

// 根据id删除搜索历史
exports.delSearchHistoryById = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 根据用户传递的id一级用户id删除搜索历史
  const sql = `delete from search_history where id=? and user_id=?`
  db.query(sql, [req.body.id, req.auth.id], (err, result) => {
    if (err) return res.cc(err)
    if (result.affectedRows === 0) return res.cc('删除失败！')
    res.cc('删除成功！', 0)
  })
}

// 清空搜索历史
exports.clearSearchHistory = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 根据用户id删除搜索历史
  const sql = `delete from search_history where user_id=?`
  db.query(sql, [req.auth.id], (err, result) => {
    if (err) return res.cc(err)
    if (result.affectedRows === 0) return res.cc('删除失败！')
    res.cc('删除成功！', 0)
  })
}

// 提交订单
exports.submitOrder = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取用户传递的数据
  const goods_ids = JSON.parse(req.body.goods_ids)
  const address_id = req.body.address_id
  // 3. 查询用户收货地址是否存在
  const queryAddressSql = `select * from user_address where id=? and user_id=?`
  try {
    const queryAddressResult = await execTransAction([{ sql: queryAddressSql, values: [address_id, req.auth.id] }])
    if (queryAddressResult[0].rows.length === 0) return res.cc('用户收货地址不存在！')
    // 获取收货地址信息
    const { name, phone, province, city, country, address, areacode } = queryAddressResult[0].rows[0]
    // 4. 查询数据库中商品库存是否充足
    const queryStockSql = `select * from goods where id=?`
    // 5. 创建订单编号和订单创建时间
    const date = new Date()
    const orderNo = createOrderNumber()
    // // 记录操作成功的结果
    let sqlArr = []
    let successCount = 0
    for (let i = 0; i < goods_ids.length; i++) {
      const queryGoodsResult = await execTransAction([{ sql: queryStockSql, values: goods_ids[i].id }])
      if (queryGoodsResult[0].rows.length === 0) return res.cc('商品信息不存在或商品已下架！')
      if (queryGoodsResult[0].rows[0].goods_stock < goods_ids[i].count) return res.cc('提交失败，商品库存不足！')
      // 6. 将向数据库中插入用户订单数据订单数据
      const insertSql = 'insert into user_orders set ?'
      const values = {
        order_id: orderNo,
        address_id: queryAddressResult[0].rows[0].id,
        goods_id: goods_ids[i].id,
        user_id: req.auth.id,
        create_time: date,
        update_time: date,
        name,
        phone,
        province,
        city,
        country,
        address,
        areacode,
        goods_count: goods_ids[i].count,
        bus_id: queryGoodsResult[0].rows[0].bus_id
      }
      sqlArr.push({ sql: insertSql, values })
      sqlArr.push({
        sql: 'insert into bus_orders set ?',
        values: {
          order_id: orderNo,
          goods_id: goods_ids[i].id,
          goods_num: goods_ids[i].count,
          create_time: date,
          bus_id: queryGoodsResult[0].rows[0].bus_id,
          user_id: req.auth.id,
          name,
          phone,
          province,
          city,
          country,
          address
        }
      })
      successCount++
      if (successCount === goods_ids.length) {
        try {
          await execTransAction(sqlArr)
          // 7. 返回响应
          res.send({
            code: 0,
            msg: '订单提交成功！',
            data: {
              orderId: orderNo
            }
          })
        } catch (err) {
          res.cc(err)
        }
      }
    }
  } catch (err) {
    res.cc(err)
  }
}

// 从购物车提交订单
exports.fromCartAddOrder = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取用户传递的数据
  const goods_ids = JSON.parse(req.body.goods_ids)
  const address_id = req.body.address_id
  let ids = req.body.ids

  if (ids[ids.length - 1] === ',') {
    ids = ids.slice(0, -1)
  }
  ids = ids.split(',')

  // 3. 查询用户收货地址是否存在
  const queryAddressSql = `select * from user_address where id=? and user_id=?`
  try {
    const queryAddressResult = await execTransAction([{ sql: queryAddressSql, values: [address_id, req.auth.id] }])
    if (queryAddressResult[0].rows.length === 0) return res.cc('用户收货地址不存在！')
    // 获取收货地址信息
    const { name, phone, province, city, country, address, areacode } = queryAddressResult[0].rows[0]
    // 4. 查询数据库中商品库存是否充足
    const queryStockSql = `select * from goods where id=?`
    // 5. 创建订单编号和订单创建时间
    const date = new Date()
    const orderNo = createOrderNumber()

    // 记录操作成功的结果
    let sqlArr = []
    let successCount = 0
    for (let i = 0; i < goods_ids.length; i++) {
      const queryGoodsResult = await execTransAction([{ sql: queryStockSql, values: goods_ids[i].id }])
      if (queryGoodsResult[0].rows.length === 0) return res.cc('商品信息不存在或商品已下架！')
      if (queryGoodsResult[0].rows[0].goods_stock < goods_ids[i].count) return res.cc('提交失败，商品库存不足！')
      // 6. 删除数据库中购物车数据
      const delCartDataSql = `delete from user_shopcarts where user_id=? and id=?`
      sqlArr.push({ sql: delCartDataSql, values: [req.auth.id, JSON.parse(ids[i])] })
      // 7. 将向数据库中插入用户订单数据订单数据
      const insertSql = 'insert into user_orders set ?'
      const values = {
        order_id: orderNo,
        goods_id: goods_ids[i].id,
        user_id: req.auth.id,
        create_time: date,
        update_time: date,
        name,
        phone,
        province,
        city,
        country,
        address,
        areacode,
        goods_count: goods_ids[i].count,
        bus_id: queryGoodsResult[0].rows[0].bus_id,
        address_id: queryAddressResult[0].rows[0].id
      }
      sqlArr.push({
        sql: 'insert into bus_orders set ?',
        values: {
          order_id: orderNo,
          goods_id: goods_ids[i].id,
          goods_num: goods_ids[i].count,
          create_time: date,
          bus_id: queryGoodsResult[0].rows[0].bus_id,
          user_id: req.auth.id,
          name,
          phone,
          province,
          city,
          country,
          address
        }
      })
      sqlArr.push({ sql: insertSql, values })
      successCount++
      if (successCount === goods_ids.length) {
        try {
          await execTransAction(sqlArr)
          // 7. 返回响应
          res.send({
            code: 0,
            msg: '订单提交成功！',
            data: {
              orderId: orderNo
            }
          })
        } catch (err) {
          res.cc(err)
        }
      }
    }
  } catch (err) {
    res.cc(err)
  }
}

// 根据订单编号获取订单数据
exports.getOrderContentByNo = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取用户提交的订单编号获取订单数据
  const orderId = req.query.orderId
  const querySql = `select * from user_orders right join goods on user_orders.goods_id=goods.id where order_id=? and user_id=? and order_status=0`
  try {
    const queryResult = await execTransAction([{ sql: querySql, values: [orderId, req.auth.id] }])
    res.send({ data: queryResult[0].rows, msg: '订单数据获取成功！', code: 0 })
  } catch (err) {
    res.cc(err)
  }
}

// 根据状态状态获取所有订单数据
exports.getAllOrderByStatus = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 获取用户传递的status， 0表示待支付，1表示待发货，2表示待收货，3表示已完成
  const { status, page, limit } = req.query
  const sql = `select * from user_orders left join goods on user_orders.goods_id=goods.id where user_id=? and order_status=? limit ?,?`
  try {
    const queryOrderResult = await execTransAction([{ sql, values: [req.auth.id, status, (page - 1) * limit, limit * 1] }])
    res.send({ code: 0, msg: '获取订单成功', data: queryOrderResult[0].rows })
  } catch (err) {
    res.cc(err)
  }
}

// 获取所有的订单数据
exports.getAllOrders = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 获取page和limit参数
  const { page, limit } = req.query
  // 使用连接查询获取所有数据信息
  const sql = `select * from user_orders left join goods on user_orders.goods_id=goods.id where user_id=? limit ?,?`
  try {
    const queryOrderResult = await execTransAction([{ sql, values: [req.auth.id, (page - 1) * limit, limit * 1] }])
    res.send({ code: 0, data: queryOrderResult[0].rows, msg: '获取商品数据成功！' })
  } catch (err) {
    res.cc(err)
  }
}

// 根据订单编号删除订单
exports.delOrderByOrderIdAndId = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization

  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取订单编号和订单id
  const { orderId } = req.body
  // 3. 定义sql语句删除订单数据
  const sql = `delete from user_orders where order_id=? and user_id=? and (order_status=0 || order_status=3)`
  try {
    await execTransAction([{ sql, values: [orderId, req.auth.id] }])
    res.send({ code: 0, msg: '删除订单成功！' })
  } catch (err) {
    res.cc(err)
  }
}

// 根据订单编号收货
exports.orderReceipt = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization
  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 获取订单编号和订单id
  const { orderId } = req.body
  // 3. 定义sql语句修改订单状态
  const sql = `update user_orders set order_status=3 where order_id=? and user_id=?`
  try {
    await execTransAction([{ sql, values: [orderId, req.auth.id] }])
    res.cc('收货成功！', 0)
  } catch (err) {
    res.cc(err)
  }
}

// 支付
exports.orderPayment = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization
  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 支付宝数据封装
  const { orderId, totalPrice } = req.body
  // 3. 对接支付宝
  const formData = new AlipayFormData()

  formData.setMethod('get')

  formData.addField('returnUrl', 'http://www.dsl2023hcy.love:9000/order/payment/' + orderId) //回调地址

  // 商单信息
  formData.addField('bizContent', {
    outTradeNo: orderId,
    productCode: 'FAST_INSTANT_TRADE_PAY',
    subject: '商品',
    body: '支付商家相应的商品金额...',
    timeout_express: '1800s', //超时
    total_amount: totalPrice
  })
  try {
    let result = await alipaySdk.exec('alipay.trade.wap.pay', {}, { formData: formData })
    // 返回响应
    res.send({
      success: 'true',
      code: 0,
      data: result
    })
  } catch (err) {
    res.cc(err)
  }
}

// 查看支付结果
exports.queryOrderMayResult = async (req, res) => {
  // 1. 判断用户token是否正确
  const token = req.headers.authorization
  // 获取redis数据库中的token
  const redisToken = await redisClient.get('user_token_' + req.auth.id)
  // redis数据库中token不存在
  if (!redisToken) {
    return res.cc('身份信息已过期！', 403)
  }
  // 用户携带的token与redis token不一致
  if (token !== redisToken) {
    return res.cc('用户身份信息错误！', 403)
  }

  // 2. 查看支付状态
  let orderId = req.query.orderId
  const formData = new AlipayFormData()
  formData.setMethod('get')
  formData.addField('bizContent', {
    outTradeNo: orderId
  })
  // 通过该接口主动查询订单状态
  try {
    const result = await alipaySdk.exec('alipay.trade.query', {}, { formData: formData })
    const queryResult = await axios({ method: 'GET', url: result })
    let r = queryResult.data.alipay_trade_query_response
    if (r.code === '10000') {
      // 接口调用成功
      switch (r.trade_status) {
        case 'WAIT_BUYER_PAY':
          res.send({
            success: true,
            message: 'success',
            code: 200,
            timestamp: new Date().getTime(),
            result: {
              status: 0,
              massage: '交易创建，等待买家付款'
            }
          })
          break
        case 'TRADE_CLOSED':
          res.send({
            success: true,
            message: 'success',
            code: 200,
            timestamp: new Date().getTime(),
            result: {
              status: 1,
              massage: '未付款交易超时关闭，或支付完成后全额退款'
            }
          })
          break
        case 'TRADE_SUCCESS':
          // 3. 将数据库中的订单状态更改为待发货状态
          const sql = `update user_orders set order_status=1,update_time=? where user_id=? and order_id=? and order_status=0`
          // 更改商家订单状态
          const updateBusOrderSql = `update bus_orders set order_status=1,payment_time=? where user_id=? and order_id=? and order_status=0`
          try {
            // 4. 将商品库存和商品销量更新
            // 根据订单号查询商品id和商品数量
            const queryGoodsIdCountSql = `select goods_count,goods_id,goods_stock,goods_sell_num, goods_price,goods.bus_id from user_orders left join goods on user_orders.goods_id=goods.id where order_id=? and user_id=?`
            const queryResult = await execTransAction([{ sql: queryGoodsIdCountSql, values: [orderId, req.auth.id] }])
            const sqlArr = [
              { sql, values: [new Date(), req.auth.id, orderId] },
              {
                sql: updateBusOrderSql,
                values: [new Date(), req.auth.id, orderId]
              }
            ]
            queryResult[0].rows.forEach((item) => {
              sqlArr.push(
                {
                  sql: `update goods set goods_stock=goods_stock-?,goods_sell_num=goods_sell_num+?,update_time=? where id=?`,
                  values: [item.goods_count, item.goods_count, new Date(), item.goods_id]
                },
                {
                  sql: 'insert into bus_account set ?',
                  values: {
                    order_id: orderId,
                    payment_time: new Date(),
                    account_price: item.goods_count * item.goods_price,
                    goods_id: item.goods_id,
                    bus_id: item.bus_id
                  }
                }
              )
            })
            await execTransAction(sqlArr)
            res.send({
              success: true,
              message: 'success',
              code: 200,
              timestamp: new Date().getTime(),
              result: {
                status: 2,
                massage: '交易支付成功'
              }
            })
          } catch (err) {
            res.cc(err)
          }

          break
        case 'TRADE_FINISHED':
          res.send({
            success: true,
            message: 'success',
            code: 200,
            timestamp: new Date().getTime(),
            result: {
              status: 3,
              massage: '交易结束，不可退款'
            }
          })
          break
        default:
          res.send({
            success: true,
            message: 'success',
            code: 200,
            timestamp: new Date().getTime(),
            result: {
              status: 3,
              massage: '未知交易结果！'
            }
          })
      }
    } else if (r.code === '40004') {
      res.cc(r.sub_msg)
    }
  } catch (err) {
    res.cc(err)
  }
}
//#endregion
